package pl.koziczak.knowledgeintegration.model.builder;


import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.Text;

import pl.koziczak.knowledgeintegration.model.Class;
import pl.koziczak.knowledgeintegration.model.Element;


public class ModelBuilder {
	
	private static ModelBuilder instance;
	
	private ModelBuilder() {
		//Sigleton
	}

	public static ModelBuilder getInstance() {
		if(instance==null)
			instance = new ModelBuilder();
		return instance;
	}
	
	
	public Class build(Document document){
		String path = "/";
		
		document.getDocumentElement().normalize();
		
		
		return parseNode(document.getDocumentElement(), null, path);
	}
	
	private Class parseNode(Node element, Class parentClass, String path) {
		Class klasa = new Class();
		klasa.setParentClass(parentClass);
		klasa.setName(element.getNodeName());
		klasa.setFullPath(path+"/"+element.getNodeName());
		/*
		 * parse elements
		 */
		
		for(int i=0; i<element.getChildNodes().getLength();i++) {
			Node child = element.getChildNodes().item(i);
				if(hasOnlyTextChildren(child) && !isEmptyName(child))
					klasa.addElement(createElement(child, klasa.getFullPath(), false));
		}
		
		/*
		 * parse attributes
		 */
		for(int i=0;i<element.getAttributes().getLength();i++) {
			Node child = element.getAttributes().item(i);
			
			klasa.addElement(createElement(child, klasa.getFullPath(), true));
		}
		
		for(int i=0; i<element.getChildNodes().getLength();i++) {
			Node child = element.getChildNodes().item(i);
			if(!hasOnlyTextChildren(child) && !isEmptyName(child))
				klasa.addSubClass(parseNode(child, klasa, klasa.getFullPath()));
		}
		
		return klasa;
	}
	
	private boolean hasValue(Node node) {
		return node.getNodeValue()!=null && !node.getNodeValue().equals("");
	}
	
	private boolean hasChildren(Node node) {
		return (node.getChildNodes() !=null && node.getChildNodes().getLength()>0)
				|| (node.getAttributes()!=null &&node.getAttributes().getLength()>0); 
	}
	
	private Element createElement(Node node, String path, boolean attribute) {
		Element element = new Element();
		element.setAttribute(attribute);
		element.setValue(getValue(node));
		element.setFullPath(path+"/"+node.getNodeName());
		element.setName(node.getNodeName());
		return element;
	}
	
	private boolean isDefferedText(Node node) {
		return node.getNodeType()== Node.TEXT_NODE;
	}
	
	private boolean isEmptyName(Node node) {
		return node.getNodeName()==null || (node instanceof Text && node.getNodeValue().trim().length()==0);
	}
	
	private boolean hasOnlyTextChildren(Node node) {
		boolean result = true;
		for(int i =0;i<node.getChildNodes().getLength();i++) {
			if(!(node.getChildNodes().item(i) instanceof Text)) {
				result= false;
				break;
			}
		}
		return result;
	}
	
	private String getValue(Node node) {
		String result = "";
		for(int i =0;i<node.getChildNodes().getLength();i++) {
				result= node.getChildNodes().item(i).getNodeValue();
		}
		return result;
	}
	
}
